package com.hippy.erya.core.schedue.spring;


import com.hippy.erya.common.DateUtil;
import com.hippy.erya.entity.*;
import com.hippy.erya.impl.*;
import com.hippy.erya.mapper.CostingMapper;
import com.hippy.erya.mapper.MessageMapper;
import com.hippy.erya.mapper.RawMaterialDailyLossMapper;
import lombok.Data;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
public class CostingJob {

    @Autowired
    private OrderDetailServiceImpl orderDetailService;

    @Autowired
    private DishServiceImpl dishService;

    @Autowired
    private RawMaterialDictionaryServiceImpl rawMaterialDictionaryService;

    @Autowired
    private RawMaterialLossServiceImpl rawMaterialLossService;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private RawMaterialDailyLossMapper rawMaterialDailyLossMapper;

    @Autowired
    private RawMaterialServiceImpl rawMaterialService;

    @Autowired
    private CostingMapper costingMapper;


    public void startCosting() {
        // 从订单表获取昨天数据 -> 计算每笔订单产生的原材料开销 -> 统计每个原材料的剩余量 -> 写入原材料每天余量表
        // 从订单表获取昨天数据 -> 统计总材料成本 + 总收入 -> 计算总利润
        Date yesterdaytDate = DateUtil.getYesterdaytDate();
        List<OrderDetailDO> orderDetailDOS = orderDetailService.queryOrderDetails(DateUtil.getYesterdaytDate(), "");
        if (CollectionUtils.isEmpty(orderDetailDOS)) {
            return;
        }
        Map<String, List<OrderDetailDO>> userCodeMap = new HashMap<>();
        orderDetailDOS.forEach(orderDetailDO -> {
            userCodeMap.computeIfAbsent(orderDetailDO.getUserCode(), k -> new ArrayList<>()).add(orderDetailDO);
        });
        userCodeMap.forEach((userCode, orderDetailDOs) -> {
            Map<String, String> dictionaryMap = rawMaterialDictionaryService.codeToName(userCode);
            Map<String, RawMaterialLossDO> rawMaterialLossDOMap = rawMaterialLossService.queryAllCode(userCode);
            Map<String, RawMaterialDO> rawMaterialDOMap = rawMaterialService.queryAll(userCode);
            Map<String, Integer> usedMerteriaMap = new HashMap<>();
            DoubleWrapper totalIncomeAmount = new DoubleWrapper();
            orderDetailDOs.forEach(orderDetailDO -> {
                try {
                    totalIncomeAmount.setAmount(totalIncomeAmount.getAmount() + orderDetailDO.getOrderPrice());
                    String dishName = orderDetailDO.getDishName();
                    DishDO dishDO = dishService.queryByDishName(userCode, dishName);
                    if (dishDO == null) {
                        saveMessage(userCode, dishName + "未配置在菜品中!");
                        return;
                    }
                    String dishMaterialList = dishDO.getDishMaterialList();
                    String[] dishCodeArray = StringUtils.split(dishMaterialList, ";");
                    if (ArrayUtils.isEmpty(dishCodeArray)) {
                        saveMessage(userCode, dishName + "未配置食材清单!");
                        return;
                    }
                    for (String dishCode : dishCodeArray) {
                        usedMerteriaMap.put(dishCode, usedMerteriaMap.getOrDefault(dishCode, 0) + 1);
                    }
                } catch (Exception e) {
                    // saveMessage(userCode, "执行异常");
                }
            });

            DoubleWrapper totalCostAmount = new DoubleWrapper();
            usedMerteriaMap.forEach((code, count) -> {
                RawMaterialDO rawMaterialDO = rawMaterialDOMap.get(code);
                double unitPricePergram = rawMaterialDO.getUnitPricePergram();
                RawMaterialLossDO rawMaterialLossDO = rawMaterialLossDOMap.get(code);
                if (rawMaterialLossDO == null) {
                    String name = dictionaryMap.get(code);
                    saveMessage(userCode, name + "未配置食材损耗!");
                    return;
                }
                saveDailyLoss(code, rawMaterialLossDO.getLossQuantity() * count, userCode, yesterdaytDate);
                totalCostAmount.setAmount(totalCostAmount.getAmount() + unitPricePergram * rawMaterialLossDO.getLossQuantity() * count);
            });
            saveCosting(userCode, totalIncomeAmount, totalCostAmount, yesterdaytDate);
        });
    }

    public void startCosting(String userCode, List<OrderDetailDO> orderDetailDOs, Date orderDate) {
        Map<String, String> dictionaryMap = rawMaterialDictionaryService.codeToName(userCode);
        Map<String, RawMaterialLossDO> rawMaterialLossDOMap = rawMaterialLossService.queryAllCode(userCode);
        Map<String, RawMaterialDO> rawMaterialDOMap = rawMaterialService.queryAll(userCode);
        Map<String, Integer> usedMerteriaMap = new HashMap<>();
        DoubleWrapper totalIncomeAmount = new DoubleWrapper();
        orderDetailDOs.forEach(orderDetailDO -> {
            try {
                totalIncomeAmount.setAmount(totalIncomeAmount.getAmount() + orderDetailDO.getOrderPrice());
                String dishName = orderDetailDO.getDishName();
                DishDO dishDO = dishService.queryByDishName(userCode, dishName);
                if (dishDO == null) {
                    saveMessage(userCode, dishName + "未配置在菜品中!");
                    return;
                }
                String dishMaterialList = dishDO.getDishMaterialList();
                String[] dishCodeArray = StringUtils.split(dishMaterialList, ";");
                if (ArrayUtils.isEmpty(dishCodeArray)) {
                    saveMessage(userCode, dishName + "未配置食材清单!");
                    return;
                }
                for (String dishCode : dishCodeArray) {
                    usedMerteriaMap.put(dishCode, usedMerteriaMap.getOrDefault(dishCode, 0) + 1);
                }
            } catch (Exception e) {
                // saveMessage(userCode, "执行异常");
            }
        });

        DoubleWrapper totalCostAmount = new DoubleWrapper();
        usedMerteriaMap.forEach((code, count) -> {
            RawMaterialDO rawMaterialDO = rawMaterialDOMap.get(code);
            double unitPricePergram = rawMaterialDO.getUnitPricePergram();
            RawMaterialLossDO rawMaterialLossDO = rawMaterialLossDOMap.get(code);
            if (rawMaterialLossDO == null) {
                String name = dictionaryMap.get(code);
                saveMessage(userCode, name + "未配置食材损耗!");
                return;
            }
            double totalCost = rawMaterialLossDO.getLossQuantity() * count;
            saveDailyLoss(code, rawMaterialLossDO.getLossQuantity() * count, userCode, orderDate);
            totalCostAmount.setAmount(totalCostAmount.getAmount() + unitPricePergram * rawMaterialLossDO.getLossQuantity() * count);
            rawMaterialDO = rawMaterialService.queryByDate(code, orderDate);
            if (rawMaterialDO == null) {
                String name = dictionaryMap.get(code);
                saveMessage(userCode, name + "未配置食材损耗!");
                return;
            }
            double buyQuantity = rawMaterialDO.getBuyQuantity();
            double remain = buyQuantity - totalCost;
            if (remain < 20) {
                String name = dictionaryMap.get(code);
                saveMessage( userCode, "食材【" + name + "】库存仅剩【" + remain + "】(斤), 请及时补充!");
            }
        });
        saveCosting(userCode, totalIncomeAmount, totalCostAmount, orderDate);
    }



    public void costingOrderDetail(Date orderDate, String userCode) {
        List<OrderDetailDO> orderDetailDOS = orderDetailService.queryOrderDetails(orderDate, userCode);
        if (CollectionUtils.isEmpty(orderDetailDOS)) {
            return;
        }
        startCosting(userCode, orderDetailDOS, orderDate);
    }


    private void saveCosting(String userCode, DoubleWrapper totalIncomeAmount, DoubleWrapper totalCostAmount, Date orderDate) {
        CostingDO costingDO = new CostingDO();
        costingDO.setCreatedBy("系统自动执行");
        costingDO.setCreatedBy("系统自动执行");
        costingDO.setCostingDate(orderDate);
        costingDO.setUserCode(userCode);
        costingDO.setRawMaterialCost(totalCostAmount.getAmount());
        costingDO.setOrderAllIncome(totalIncomeAmount.getAmount());
        costingDO.setAllProfit(totalIncomeAmount.getAmount() - totalCostAmount.getAmount());
        costingDO.setStatus("0");
        costingMapper.insert(costingDO);
    }


    private void saveDailyLoss(String code, double loss, String userCode, Date orderDate) {
        RawMaterialDailyLossDO rawMaterialDailyLossDO = new RawMaterialDailyLossDO();
        rawMaterialDailyLossDO.setCreatedBy("系统自动执行");
        rawMaterialDailyLossDO.setCreatedBy("系统自动执行");
        rawMaterialDailyLossDO.setUserCode(userCode);
        rawMaterialDailyLossDO.setRawMaterialCode(code);
        rawMaterialDailyLossDO.setRawMaterialLossNum(loss);
        rawMaterialDailyLossDO.setBusinessDate(orderDate);
        rawMaterialDailyLossMapper.insert(rawMaterialDailyLossDO);


    }



    private void saveMessage(String userCode, String message) {
        MessageDO messageDO = new MessageDO();
        messageDO.setUserCode(userCode);
        messageDO.setCreatedBy("系统自动执行");
        messageDO.setCreatedBy("系统自动执行");
        messageDO.setStatus("未读");
        messageDO.setSendTime(DateUtil.getCurrentDate());
        messageDO.setMessage(message);
        messageMapper.insert(messageDO);
    }

    @Data
    private static class DoubleWrapper {
        private double amount;
    }

}
